package generics;


// 泛型其实就一个待定类型，在定义时并不明确是什么类型，而是需要到使用时才会确定对应的泛型类型
// 泛型将数据类型的确定控制在了编译阶段，在编写代码的时候就能明确泛型的类型，如果类型不符合，将无法通过编译！
// 因为是具体使用对象时才会明确具体类型，所以说静态方法中是不能用的
// 且不能通过这个不确定的类型变量就去直接创建对象和对应的数组（类型形参'T'不能直接实例化）
//



// 定义一个泛型接口 Processor
interface Processor<T> {    //泛型类需要使用<>，我们需要在里面添加1 - N个类型变量
    T process(T input);
}

// 1. 泛型类与多态
class StringProcessor implements Processor<String> {
    @Override
    public String process(String input) {
        return input.toUpperCase();
    }
}

// 定义泛型类 GenericClass
class GenericClass<T> {
    private T value;    // T会根据使用时提供的类型自动变成对应类型，但是一旦确定，那么就不能修改了

    public GenericClass(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    // 3. 泛型方法与显示类型擦除
    public static <U> void printArray(U[] array) {
        for (U element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }

    public void showTypeErase() {
        // 在运行时，value 的类型被擦除为 Object
        System.out.println("Runtime type of value: " + value.getClass().getName());
    }
}

// 2. 泛型的界限
class NumberProcessor<T extends Number> {
    private T value;

    public NumberProcessor(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public double getValueAsDouble() {
        return value.doubleValue();
    }
}

// 主类
public class GenericClassDemo {
    public static void main(String[] args) {
        // 1. 泛型类与多态
        Processor<String> stringProcessor = new StringProcessor();

        // 在方法中使用待确定类型的变量时，因为此时并不明确具体是什么类型，那么默认会认为这个变量是一个Object类型的变量
        System.out.println("Processed String: " + stringProcessor.process("hello")); // 输出: Processed String: HELLO

        // 2. 泛型的界限
        NumberProcessor<Integer> integerProcessor = new NumberProcessor<>(10);
        System.out.println("NumberProcessor value: " + integerProcessor.getValue()); // 输出: NumberProcessor value: 10
        System.out.println("NumberProcessor value as double: " + integerProcessor.getValueAsDouble()); // 输出: 10.0

        // 3. 泛型方法
        Integer[] integers = {1, 2, 3, 4, 5};
        GenericClass.printArray(integers); // 输出: 1 2 3 4 5

        String[] strings = {"a", "b", "c"};
        GenericClass.printArray(strings); // 输出: a b c

        // 4. 类型擦除
        GenericClass<String> stringGeneric = new GenericClass<>("example");
        stringGeneric.showTypeErase(); // 输出: Runtime type of value: java.lang.String
    }
}